#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <sys/resource.h>

#include <daemon.h>
#include <log.h>

void ShowVersion ()
{
	printf("%s v%s\n",progname, version);
}

void ShowUsage ()
{
	ShowVersion();
	printf("Usage:\n    %s [-d] [-f config.conf] [-t dirty.conf] %s\n", progname, usage_argv);
}

int DaemonInit (int argc, char **argv)
{
	int c;

	while ((c = getopt (argc, argv, "df:t:hv")) != -1) {
		switch (c) {
		case 'd':
			background = 0;
			break;
		case 'f':
			strncpy (confFile, optarg, sizeof (confFile) - 1);
			break;
		case 't':
			strncpy (dirtyFile, optarg, sizeof (dirtyFile) - 1);
			break;
		case 'h':
			ShowUsage ();
			exit(0);
		case 'v':
			ShowVersion ();
			exit(0);
		case '?':
			ShowUsage ();
			exit(-1);
		}
	}


	const char *home = getenv("FILTERD_HOME");
	if(home == NULL)
	{
		printf("Get env FILTERD_HOME faild. Use default log dir /tmp/\n") ;
		init_log(progname, "/tmp/");		
	}
	else
	{
		char dir[256] = {0};
		sprintf(dir, "%s/logs/", home);
		printf("Get env FILTERD_HOME %s\n", home) ;
		init_log(progname, dir);
	}

	
	
	log_info("%s v%s: starting....", progname, version);
	
	return 0;
}

static void sigterm_handler(int signo) 
{
    log_info("be stoped by signal:%d",signo);
    stop = 1;
}

void DaemonWait (void)
{
	while (!stop)
	{
		sleep (5000);
#if MEMCHECK
		log_debug("memory allocated %lu virtual %lu", count_alloc_size(), count_virtual_size());
#endif
	}
}

int DaemonStart()
{
	struct sigaction sa;
	sigset_t sset;
	
	memset(&sa, 0, sizeof(sa));
	sa.sa_handler = sigterm_handler;
	sigaction(SIGINT, &sa, NULL);
	sigaction(SIGTERM, &sa, NULL);
	sigaction(SIGQUIT, &sa, NULL);
	sigaction(SIGHUP, &sa, NULL);

	signal(SIGPIPE,SIG_IGN);	
	signal(SIGCHLD,SIG_IGN);	

	sigemptyset(&sset);
	sigaddset(&sset, SIGSEGV);
	sigaddset(&sset, SIGBUS);
	sigaddset(&sset, SIGABRT);
	sigaddset(&sset, SIGILL);
	sigaddset(&sset, SIGCHLD);
	sigaddset(&sset, SIGFPE);
	sigprocmask(SIG_UNBLOCK, &sset, &sset);
	
	return background ? daemon (1, 1) : 0;
}

void DaemonCleanup(void)
{

}

int DaemonSetFdLimit(int maxfd)
{
	struct rlimit rlim;
	if(maxfd)
	{
		/* raise open files */
		rlim.rlim_cur = maxfd;
		rlim.rlim_max = maxfd;
		if (setrlimit(RLIMIT_NOFILE, &rlim) == -1) {
			log_notice("Increase FdLimit failed, set val[%d] errmsg[%s]",maxfd,strerror(errno));
			return -1;
		}
	}
	return 0;
}

int DaemonEnableCoreDump(void)
{
	struct rlimit rlim;
	/* allow core dump */
	rlim.rlim_cur = RLIM_INFINITY;
	rlim.rlim_max = RLIM_INFINITY;
	if(setrlimit(RLIMIT_CORE, &rlim) == -1)
	{
		log_notice("EnableCoreDump failed, errmsg[%s]",strerror(errno));
		return -1;
	}
	return 0;
}

